﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;

namespace WebStorage.Models
{
    public class WebFileSystem
    {
        public System.Guid ID { get; set; }
        public string Title { get; set; }
        public bool IsFolder { get; set; }
        public string FullName { get; set; }
        public string Hashcode { get; set; }
        public string FileType { get; set; }
        public int FileSize { get; set; }
        public System.DateTime DateCreated { get; set; }
        public System.DateTime DateUpdated { get; set; }
        public string DateCreatedString { get; set; }
        public string DateUpdatedString { get; set; }
        public bool IsPublic { get; set; }
    }

    public class DbHelper
    {
        private WebStorageEntities _context;

        public WebStorageEntities Context
        {
            get
            {
                if (_context == null)
                    _context = new WebStorageEntities();
                return _context;
            }
        }

        public WebUser Login(string username, string password)
        {
            return Context.WebUser.Where(t => t.LoginID == username && t.Passwords == password).FirstOrDefault();
        }

        public FileExistsStatus CheckFile(Guid userid, string hashcode)
        {
            var file = Context.WebFile.FirstOrDefault(t => t.Hashcode == hashcode);

            if (file == null)
                return FileExistsStatus.NotExists;
            if (file.IsPublic)
                return FileExistsStatus.Public;
            if (file.UserID == userid)
                return FileExistsStatus.Self;
            else
            {
                var share = Context.FolderFile.Count(t => t.FileID == file.ID && t.WebFolder.UserID == userid);
                if (share > 0)
                    return FileExistsStatus.Share;
                else
                    return FileExistsStatus.Other;
            }
        }

        public void AddFile(string title, string filepath, string filetype, Guid userid, Guid? folderid)
        {
            int filesize = 0;
            var hashcode = GetMD5HashFromFile(filepath, out filesize);
            var file = Context.WebFile.Add(new WebFile()
            {
                ID = Guid.NewGuid(),
                DateCreated = DateTime.Now,
                DateUpdated = DateTime.Now,
                FileSize = filesize,
                FileType = filetype,
                FolderID = folderid,
                FullName = Path.GetFileName(filepath),
                IsPublic = false,
                Title = title,
                UserID = userid,
                Hashcode = hashcode
            });
            if (folderid.HasValue)
                Context.FolderFile.Add(new FolderFile()
                {
                    ID = Guid.NewGuid(),
                    FileID = file.ID,
                    FolderID = folderid.Value,
                });

            Context.SaveChanges();
        }

        private string GetMD5HashFromFile(string filepath, out int filezise)
        {
            try
            {
                FileStream file = new FileStream(filepath, FileMode.Open);
                MD5 md5 = new MD5CryptoServiceProvider();
                byte[] retVal = md5.ComputeHash(file);
                filezise = (int)file.Length;
                file.Close();

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < retVal.Length; i++)
                {
                    sb.Append(retVal[i].ToString("x2"));
                }
                return sb.ToString();
            }
            catch (Exception ex)
            {
                throw new Exception("GetMD5HashFromFile() fail,error:" + ex.Message);
            }
        }

        public List<WebFileSystem> GetFileSystem(Guid uId, Guid? folderId = null)
        {
            List<WebFileSystem> sys = new List<WebFileSystem>();
            var folder = Context.WebFolder.Where(t => t.ParentID == folderId && (t.UserID == uId || t.IsPublic)).Select(t => new WebFileSystem() { ID = t.ID, IsFolder = true, Title = t.Title, IsPublic = t.IsPublic, DateUpdated = t.DateUpdate }).ToList();
            sys.AddRange(folder);

            if (folderId.HasValue)
            {
                var file = Context.FolderFile.Where(t => t.FolderID == folderId.Value).Select(t => t.WebFile).Select(t => new WebFileSystem() { ID = t.ID, Title = t.Title, IsFolder = false, DateCreated = t.DateCreated, DateUpdated = t.DateUpdated, FileSize = t.FileSize, FileType = t.FileType, FullName = t.FullName, Hashcode = t.Hashcode, IsPublic = t.IsPublic }).ToList();
                sys.AddRange(file);
            }
            else
            {
                var file = Context.WebFile.Where(t => t.FolderID == folderId && (t.UserID == uId || t.IsPublic)).Select(t => new WebFileSystem() { ID = t.ID, Title = t.Title, IsFolder = false, DateCreated = t.DateCreated, DateUpdated = t.DateUpdated, FileSize = t.FileSize, FileType = t.FileType, FullName = t.FullName, Hashcode = t.Hashcode, IsPublic = t.IsPublic }).ToList();
                sys.AddRange(file);
            }
            return sys;
        }
    }

    public enum FileExistsStatus
    {
        Public,
        Self,
        Other,
        Share,
        NotExists
    }
}